package com.padakeji.android.ui.widget;

import android.content.Context;
import android.os.AsyncTask;
import android.support.annotation.LayoutRes;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;

import com.padakeji.android.ui.R;

import java.util.concurrent.Executors;

/**
 * Created by atanl on 2015/10/23.
 */
public class AutoLoadRecycler extends RecyclerViewX {

    private static final String TAG = "AutoLoadRecycler";

    public static abstract class AutoLoadListener<T>  {
        public abstract T loadInBackground();
        final void finish(Object result) {
            onLoadFinish((T) result);
        }
        public abstract void onLoadFinish(T result);
        public abstract void onLoadFail(Throwable e);
    }

    private AutoLoadListener mAutoLoadListener;

    private boolean mIsAutoLoadEnable = false;
    private int mAutoLoadThreshold = 0;
    private View mLoadingView;

    public AutoLoadRecycler(Context context) {
        this(context, null);
    }

    public AutoLoadRecycler(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AutoLoadRecycler(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        setLoadingView(R.layout.padaui_auto_load_recycler_loading);

        addOnScrollListener(new OnScrollListener() {

            Boolean isLoading = false;

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

                if (!mIsAutoLoadEnable) {
                    return;
                }
                synchronized (isLoading) {
                    if (isLoading) {
                        return;
                    }

                    // 保证更改自动加载启动阀值mAutoLoadThreshold时，currentAutoLoadThreshold保持不变。
                    int currentAutoLoadThreshold = mAutoLoadThreshold;

                    final AutoLoadRecycler mRecycler = (AutoLoadRecycler) recyclerView;
                    LayoutManager layoutManager = mRecycler.getLayoutManager();
                    LayoutManagerType t = getLayoutManageType(layoutManager);
                    if (t == null) {
                        Log.d(TAG, "LayoutManage has not been set, please set it first.");
                    }
                    switch (t) {
                        case Linear:
                            LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
                            int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
                            int itemCount = linearLayoutManager.getItemCount();
                            if (itemCount - lastVisibleItemPosition <= currentAutoLoadThreshold + 1) {
                                triggerAutoLoad();
                            }
                            break;
                        default:
                            break;

                    }
                }

            }

            private void triggerAutoLoad() {
                new AsyncTask<Void, Void, Object>() {

                    // 其实是对mLoadingView的引用。保证切换mLoadingView时，currentLoadingView保持不变。
                    private View currentLoadingView;

                    @Override
                    protected void onPreExecute() {
                        isLoading = true;
                        addLoadingView();
                    }

                    @Override
                    protected Object doInBackground(Void... params) {
                        if (mAutoLoadListener != null) {
                            try {
                                return mAutoLoadListener.loadInBackground();
                            } catch (Exception e) {
                                try {
                                    mAutoLoadListener.onLoadFail(e);
                                } catch (Exception e1) {
                                    e1.printStackTrace();
                                }
                            }
                        }
                        return null;
                    }

                    @Override
                    protected void onPostExecute(Object o) {
                        removeLoadingView();
                        if (mAutoLoadListener != null) {
                            try {
                                mAutoLoadListener.finish(o);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        isLoading = false;
                    }

                    private void addLoadingView() {
                        if (getFooterCount() != 0) {
                            Log.d("fuck", "you");
                        }
                        if (mLoadingView != null) {
                            currentLoadingView = mLoadingView;
                            addFooterView(mLoadingView);
                        }
                    }

                    private void removeLoadingView() {
                        if (currentLoadingView != null) {
                            removeFooterView(currentLoadingView);
                            currentLoadingView = null;
                        }
                    }

                }.executeOnExecutor(Executors.newSingleThreadExecutor());
            }

        });
    }

    public void setAutoLoadListener(AutoLoadListener<?> l) {
        mAutoLoadListener = l;
    }

    public void enableAutoLoad() {
        enableAutoLoad(0);
    }

    public void enableAutoLoad(int threshold) {
        if (threshold < 0) {
            threshold = 0;
        }
        mAutoLoadThreshold = threshold;
        mIsAutoLoadEnable = true;
    }

    public void disableAutoLoad() {
        mIsAutoLoadEnable = false;
    }

    public void setLoadingView(View v) {
        this.mLoadingView = v;
    }

    public void setLoadingView(@LayoutRes int id) {
        View v = LayoutInflater.from(getContext()).inflate(R.layout.padaui_auto_load_recycler_loading, null, false);
        setLoadingView(v);
    }

    private LayoutManagerType getLayoutManageType(LayoutManager layoutManager) {
        if (layoutManager == null) {
            return null;
        }
        if (layoutManager instanceof LinearLayoutManager) {
            return LayoutManagerType.Linear;
        } else if (layoutManager instanceof GridLayoutManager) {
            return LayoutManagerType.Grid;
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            return LayoutManagerType.StaggeredGrid;
        } else {
            throw new RuntimeException("Unsupported LayoutManager used. Valid ones are LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager.");
        }
    }

    private enum LayoutManagerType {
        Linear,
        Grid,
        StaggeredGrid,
    }


}
